package cn.wzc.crystal.platform.query.impl;

import cn.wzc.crystal.platform.query.QueryLoadException;
import cn.wzc.crystal.platform.query.QueryProvider;
import lombok.Setter;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.springframework.util.ResourceUtils;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.nio.file.Paths;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 从 classpath 搜索查询SQL 文件
 */
@Setter
public class DefaultQueryProvider implements QueryProvider {
	/**
	 * 查询缓存
	 */
	private final Map<String, String> cache = new ConcurrentHashMap<>();


	/**
	 * 查询文件所在目录
	 */
	private String resourceDir = "classpath:/query";
	/**
	 * 是否对文件进行缓存
	 */
	private boolean cacheable = true;

	/**
	 * 文件后缀
	 */
	private String stuff = ".sql";


	@Override
	public String loadTemplate(String name) {
		if (cacheable) {
			return cache.computeIfAbsent(name, this::loadFromResourceDir);
		}
		return this.loadFromResourceDir(name);
	}

	private String loadFromResourceDir(String name) {
		String path = Paths.get(resourceDir, name + stuff).toString();
		try {
			if (path.startsWith(ResourceUtils.CLASSPATH_URL_PREFIX)) {
				path = path.substring(ResourceUtils.CLASSPATH_URL_PREFIX.length() + 1);
				final URL url = getClass().getClassLoader().getResource(path);
				if (null == url) {
					throw new QueryLoadException("查询 sql 文件不存在,请检查");
				}
				try (InputStream is = url.openStream()) {
					final byte[] sqlBir = IOUtils.toByteArray(is);
					return new String(sqlBir);
				}
			}
			if (path.startsWith("file:")) {
				final File file = ResourceUtils.getFile(path);
				return FileUtils.readFileToString(file);
			}
			throw new QueryLoadException("不能识别 SQL 文件存放位置:" + path);
		} catch (FileNotFoundException e) {
			throw new QueryLoadException("查询 sql 文件不存在,请检查", e);
		} catch (IOException e) {
			throw new QueryLoadException("查询 SQL 文件读取失败,请检查", e);
		}
	}

}
